package com.mall.malladminbackend.utils;

import com.mall.malladminbackend.config.AppProperties;
import com.mall.malladminbackend.enums.JwtValidateInfo;
import com.google.common.collect.ImmutableMap;
import io.jsonwebtoken.*;
import io.jsonwebtoken.security.SignatureException;
import org.springframework.stereotype.Component;

import javax.crypto.spec.SecretKeySpec;
import java.security.Key;
import java.util.Base64;
import java.util.Date;
import java.util.List;
import java.util.Set;

@Component
public class JwtUtils {

    private final Key key;
    private final Long expiration;

    public JwtUtils(AppProperties appProperties) {
        key = new SecretKeySpec(Base64.getDecoder().decode(appProperties.getJwt().getKey()), "HmacSHA512");
        expiration = appProperties.getJwt().getExpiration();
    }

    // 生成一个jwt, 其中还包含了用户对于接口的操作权限
    public String generateJwt(String subject, Set<String> authorizes) {
        return Jwts.builder()
                .setSubject(subject)
                .addClaims(ImmutableMap.of("authorizes", authorizes))  // 在jwt中额外的设置用户的权限
                .setIssuedAt(new Date())      // Jwt的颁发时间
                .setExpiration(new Date(System.currentTimeMillis() + expiration))   // 过期时间
                .signWith(key, SignatureAlgorithm.HS512)
                .compact();  // 返回签名对应的 字符串
    }

    public String generateJwt(String subject) {
        return Jwts.builder()
                .setSubject(subject)
                .setIssuedAt(new Date())      // Jwt的颁发时间
                .setExpiration(new Date(System.currentTimeMillis() + expiration))   // 过期时间
                .signWith(key, SignatureAlgorithm.HS512)
                .compact();  // 返回签名对应的 字符串
    }

    // 验证jwt
    public JwtValidateInfo validateJwt(String jwt) {
        try {
            Claims claims = Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(jwt).getBody();
            String subject = claims.getSubject();
            // 获取用户的权限
            List<String> authorizes = claims.get("authorizes", List.class);

            return JwtValidateInfo.builder()
                    .status(JwtValidateInfo.JwtStatus.correct)
                    .subject(subject)
                    .authorizes(authorizes)
                    .build();
        }catch (ExpiredJwtException e) {
            return JwtValidateInfo.builder().status(JwtValidateInfo.JwtStatus.expired).build();
        }catch (MalformedJwtException | SignatureException | UnsupportedJwtException e) {
            return JwtValidateInfo.builder().status(JwtValidateInfo.JwtStatus.temper).build();
        }
    }
}
